import { useRef } from 'react';
import X6GraphManager from '../managers/X6GraphManager';
import NodeManager from '../nodes/NodeManager';
import { register as registerReactShape, type ReactShapeConfig } from '@antv/x6-react-shape';
import { Dnd } from '@antv/x6-plugin-dnd';
import { nanoid } from 'nanoid';
import type { Graph, Model } from '@antv/x6';
import { login } from '@/api';
import {debounce} from "lodash"
import { useStore } from '@/store';
import { getCurrentNodeOutputs, getNextNodes } from '@/utils/utils';

export type InitialDataType = {
  id: string;
  type: string;
  inputs: {
      edgeId: string;
      sourceNode: string;
  }[];
  outputs: {
      edgeId: string;
      targetNode: string;
  }[];
}[]

export type FlowsType = Record<string, { count: number }>

export function useX6Graph() {
  const dndRef = useRef<Dnd | null>(null);
  const graphRef = useRef<Graph | null>(null);
  const {flowData,setData} = useStore();

  // 初始化画布
  const initGraph = (container: HTMLElement, width?: number, height?: number, options?: object) => {
    const graph = X6GraphManager.init(container, width, height, options);
    graphRef.current = graph;
    initListener(graph);
    return graph;
  };

  // 初始化监听事件
  const initListener = (graph: Graph) => {
    if (!graph) return;
    graph.on('node:click', (e) => {
      console.log(e);
    });
    graph.on('node:mouseenter', () => togglePort(true))
    graph.on('node:mouseleave', () => togglePort(false))
    graph.on('edge:added', updateAllNodesIO);
    graph.on('edge:removed', updateAllNodesIO)
    graph.on('edge:connected', updateAllNodesIO);
    graph.on('edge:disconnected',updateAllNodesIO);

    graph.bindKey('backspace', () => {
      const cells = graph.getSelectedCells()
      if (cells.length) {
        graph.removeCells(cells)
      }
    })
    graph.bindKey(['meta+z', 'ctrl+z'], () => {
      if (graph.canUndo()) {
        graph.undo()
      }
      return false
    })
    graph.bindKey(['meta+0', 'ctrl+0'], () => {
      centerContent();
    })
  };

  const getAllNodesIO = () => {
    const graph = graphRef.current;
    if (graph) {
      const nodes = graph.getNodes();
      const nodesIO = nodes.map((node) => {
        const inputEdges = graph.getIncomingEdges(node);
        const outputEdges = graph.getOutgoingEdges(node);
        const inputs = inputEdges?.map((edge) => ({
          edgeId: edge.id,
          sourceNode: edge.getSourceCellId(),
        })) || [];
        const outputs = outputEdges?.map((edge) => ({
          edgeId: edge.id,
          targetNode: edge.getTargetCellId(),
        })) || [];
        return {
          id: node.id,
          type: node.getData().type,
          inputs,
          outputs
        }
      })
      return nodesIO;
    }
    return [];
  }

  const updateAllNodesIO = debounce(getAllNodesIO,100)



  // 初始化流程数据
  const initialData = (data:InitialDataType)=>{
    const nodeIds = data.map((node)=>node.id);
    const flows: FlowsType = nodeIds.reduce((acc, cur) => {
      acc[cur] = {
        count: 0
      }
      return acc;
    }, {} as Record<string, { count: number }>);
    setData(flows);
    return flows;
  }

  // 模拟运行
  const runFlow = async () => {
    const data = getAllNodesIO();
    const flows = initialData(data);
    console.log("data",data);
    console.log("flowData",flows);
    // 当前时间
    const startTime = new Date();
    console.log(`开始时间：${startTime}`);
    let count = 0;
    const maxIterations = 2;
    // 创建while循环 循环内的异步操作结束循环继续执行 while执行100次后停止
    while (count < maxIterations) {
      console.log(`第 ${count + 1} 次循环开始`);
      let currentWhileNodes = data.filter((node) => node.type === 'liaocang');
      let innerCount = 0;
      let shouldBreak = false;
      
      while(currentWhileNodes.length && currentWhileNodes.length > innerCount && !shouldBreak){
        const currentNode = currentWhileNodes[innerCount];
        let nodeRunCount = flows[currentNode.id]?.count || 0;
        console.log(`  【内部循环节点】${currentNode.type} 未执行前执行次数：${nodeRunCount}`);
        
        // 检查节点执行次数是否已经超过当前外部循环次数
        if(nodeRunCount > count){
          console.log(`节点 ${currentNode.id} 执行次数 ${nodeRunCount} 已超过当前循环次数 ${count}，停止内部循环`);
          shouldBreak = true;
          break;
        }
        
        if(nodeRunCount <= count){
          // await login();
          X6GraphManager.setLineColor(currentNode.outputs)
          await new Promise((resolve)=>setTimeout(resolve,1000));
          currentNode.outputs.forEach((output)=>{
            X6GraphManager.setLineText(output.edgeId, `${nodeRunCount} t/h`)
          })
          nodeRunCount ++;
          flows[currentNode.id] = { count: nodeRunCount };
          setData({ ...flows });
        }
        innerCount++;
        if(currentWhileNodes.length === innerCount){
          const flatArr = getCurrentNodeOutputs(currentWhileNodes);
          currentWhileNodes = getNextNodes(data,flatArr,flows,count);
          innerCount = 0;
        }
      }
      console.log(`【外部循环】第 ${count + 1} 次结束`);
      X6GraphManager.setLineColor();
      count++;
    }
    console.log(`循环已执行${count}次，停止`);
    // 结束时间
    const endTime = new Date();
    console.log(`结束时间：${endTime}`);
    // 计算时间差
    const timeDiff = endTime.getTime() - startTime.getTime();
    console.log(`时间差：${timeDiff} 毫秒`);
    X6GraphManager.setLineColor(true);
    // console.log(data);
  }

  // 居中画布
  const centerContent = () => {
    X6GraphManager.center();
  }

  // 获取流程数据
  const getFlowData = () => {
    const graph = graphRef.current;
    if (graph) {
      const data = graph.toJSON();
      console.log(data);
      return data;
    }
  }

  // 设置流程数据
  const setFlowData = (data: Model.FromJSONData) => {
    const graph = graphRef.current;
    if (graph) {
      graph.fromJSON(data);
    }
  }

  // 卸载画布
  const disposeGraph = () => {
    X6GraphManager.dispose();
    dndRef.current = null;
  };

  // 注册节点
  const registerNode = (name: string, config: object) => {
    NodeManager.registerNode(name, config);
  };

  // 批量注册节点
  const registerNodes = (nodes: { name: string; config: object }[]) => {
    NodeManager.registerNodes(nodes);
  };

  // 卸载节点
  const unregisterNode = (name: string) => {
    NodeManager.unregisterNode(name);
  };

  // 注册自定义 React 节点
  const registerReactNode = (options: ReactShapeConfig) => {
    registerReactShape(options);
  };

  // 添加备注节点
  const addRemarkNode = () => {
      const graph = graphRef.current;
      if (graph) {
      graph.addNode({
        shape: 'custom-basic-react-remark',
        x: 40,
        y: 40,
        width: 200,
        height: 240,
        data: {
          remark: '',
        },
        attrs: {
          body: {
            stroke: 'transparent',
            strokeWidth: 0,
            fill: 'transparent',
            rx: 6,
            ry: 6,
            refWidth: 1,
            refHeight: 1,
          },
        },
      });
      centerContent();
    }
  }

  // 初始化 Dnd
  const initDnd = (dndContainer: HTMLElement) => {
    const graph = X6GraphManager.getInstance();
    if (graph && dndContainer) {
      dndRef.current = new Dnd({
        target: graph,
        scaled: false,
        dndContainer,
      });
    }
    return dndRef.current;
  };

  // 切换显示连接桩
  const togglePort = (visible: boolean) => {
    const container = document.getElementById('graph-container')
    const ports = container?.querySelectorAll(
      '.x6-port-body'
    ) as NodeListOf<SVGElement>
    for (let i = 0, len = ports.length; i < len; i += 1) {
      ports[i].style.visibility = visible ? 'visible' : 'hidden'
    }
  };

  // 拖拽创建节点
  const dragCreateNode = (e: React.MouseEvent<HTMLElement>) => {
    const graph = X6GraphManager.getInstance();
    if (!graph || !dndRef.current) return;
    // 假设 shape、label、image 等参数都设置在标签属性上
    const shape = e.currentTarget.getAttribute('data-shape');
    const label = e.currentTarget.getAttribute('data-label');
    const image = e.currentTarget.getAttribute('data-image');
    const node = graph.createNode({
      shape: shape!,
      label: label!,
      data: {
        id: nanoid(),
        type: shape!,
      },
      attrs: {
        image: {
          'xlink:href':  image,
        },
      },
    });
    dndRef.current.start(node, e.nativeEvent);
  };

  return {
    graph: graphRef.current,
    initGraph,
    disposeGraph,
    registerNode,
    registerNodes,
    unregisterNode,
    registerReactNode,
    addRemarkNode,
    centerContent,
    initDnd,
    runFlow,
    dndRef,
    getFlowData,
    setFlowData,
    togglePort,
    dragCreateNode,
  };
}
